﻿namespace HutongGames.PlayMakerEditor
{
    using HutongGames.PlayMaker;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using UnityEditor;
    using UnityEngine;

    public class GlobalEventsWindow : EditorWindow
    {
        private double clickTime;
        private const double doubleClickTime = 0.3;
        private List<FsmEvent> filteredEvents = new List<FsmEvent>();
        private static GlobalEventsWindow instance;
        private string newEventName = "";
        private Vector2 scrollPosition;
        private string searchString = "";
        private FsmEvent selectedEvent;
        private bool sortByUsageCount;
        private readonly List<FsmEvent> unusedEvents = new List<FsmEvent>();
        private readonly Dictionary<FsmEvent, int> usageCount = new Dictionary<FsmEvent, int>();

        private void AddSelectedEventToState()
        {
            if (((this.selectedEvent != null) && (FsmEditor.SelectedFsm != null)) && !FsmEditor.SelectedFsm.HasEvent(this.selectedEvent.Name))
            {
                FsmEditor.Builder.AddEvent(this.selectedEvent.Name, true);
                FsmEditor.Inspector.ResetView();
            }
        }

        private void BuildFilteredList()
        {
            FsmEvent.SanityCheckEventList();
            this.UpdateUseCount();
            if (string.IsNullOrEmpty(this.searchString))
            {
                this.filteredEvents = new List<FsmEvent>(FsmEvent.EventList);
                this.filteredEvents.Sort();
            }
            else
            {
                this.filteredEvents.Clear();
                string str = this.searchString.ToUpper();
                foreach (FsmEvent event2 in FsmEvent.EventList)
                {
                    if (event2.Name.ToUpper().Contains(str))
                    {
                        this.filteredEvents.Add(event2);
                    }
                }
                this.filteredEvents.Sort();
            }
        }

        private static int CountEventUsage(FsmEvent fsmEvent)
        {
            if (fsmEvent == null)
            {
                return 0;
            }
            int num = 0;
            foreach (Fsm fsm in FsmEditor.FsmList)
            {
                foreach (FsmEvent event2 in fsm.Events)
                {
                    if (fsmEvent.Name == event2.Name)
                    {
                        num++;
                        break;
                    }
                }
            }
            return num;
        }

        public static void DeselectAll()
        {
            if (instance != null)
            {
                instance.selectedEvent = null;
                instance.Repaint();
            }
        }

        private void DoBottomPanel()
        {
            GUILayout.BeginHorizontal(new GUILayoutOption[0]);
            bool enabled = GUI.enabled;
            if (((FsmEditor.SelectedFsm == null) || (this.selectedEvent == null)) || FsmEditor.SelectedFsm.HasEvent(this.selectedEvent.Name))
            {
                GUI.enabled = false;
            }
            if (GUILayout.Button("Add Selected Event To FSM", new GUILayoutOption[0]))
            {
                this.AddSelectedEventToState();
            }
            GUI.enabled = enabled;
            if (FsmEditorGUILayout.HelpButton("Online Help"))
            {
                EditorCommands.OpenWikiPage(WikiPages.EventManager);
            }
            GUILayout.EndHorizontal();
            EditorGUILayout.Space();
        }

        private void DoEventEditor()
        {
            FsmEditorGUILayout.Divider(new GUILayoutOption[0]);
            if ((EditorWindow.focusedWindow == this) && ((this.selectedEvent != null) && !this.selectedEvent.IsSystemEvent))
            {
                EditorGUILayout.BeginHorizontal(new GUILayoutOption[0]);
                GUILayout.Label("Rename", new GUILayoutOption[] { GUILayout.MaxWidth(50f) });
                this.newEventName = EditorGUILayout.TextField(this.newEventName, new GUILayoutOption[0]);
                EditorGUILayout.EndHorizontal();
                string str = FsmEditor.Builder.ValidateRenameEvent(this.selectedEvent, this.newEventName);
                bool flag = string.IsNullOrEmpty(str);
                if (!flag)
                {
                    GUILayout.Box(str, FsmEditorStyles.ErrorBox, new GUILayoutOption[0]);
                }
                if (Event.current.isKey)
                {
                    if (flag && FsmEditorUtility.EnterKeyPressed())
                    {
                        this.RenameEvent();
                        GUIUtility.ExitGUI();
                    }
                    if (Event.current.keyCode == KeyCode.Escape)
                    {
                        this.newEventName = this.selectedEvent.Name;
                    }
                }
            }
        }

        private void DoEventLine(FsmEvent fsmEvent)
        {
            int num;
            this.usageCount.TryGetValue(fsmEvent, out num);
            if ((num != 0) || !FsmEditorSettings.HideUnusedEvents)
            {
                GUILayout.BeginHorizontal(((this.selectedEvent != null) && (fsmEvent.Name == this.selectedEvent.Name)) ? FsmEditorStyles.SelectedEventBox : FsmEditorStyles.TableRowBox, new GUILayoutOption[0]);
                bool enabled = GUI.enabled;
                if (fsmEvent.IsSystemEvent)
                {
                    GUI.enabled = false;
                }
                bool isGlobal = GUILayout.Toggle(fsmEvent.IsGlobal, new GUIContent("", "Global"), FsmEditorStyles.TableRowCheckBox, new GUILayoutOption[] { GUILayout.MaxWidth(17f), GUILayout.MinWidth(17f) });
                if (isGlobal != fsmEvent.IsGlobal)
                {
                    FsmEditor.Builder.SetEventIsGlobal(fsmEvent, isGlobal);
                }
                GUI.enabled = enabled;
                GUIStyle style = ((this.selectedEvent != null) && (fsmEvent.Name == this.selectedEvent.Name)) ? FsmEditorStyles.TableRowTextSelected : FsmEditorStyles.TableRowText;
                if (GUILayout.Button(fsmEvent.Name, style, new GUILayoutOption[] { GUILayout.MinWidth(base.position.width - 100f) }))
                {
                    this.SelectEvent(fsmEvent);
                    if ((Event.current.button == 1) || EditorGUI.actionKey)
                    {
                        this.GenerateUsageContextMenu(this.selectedEvent).ShowAsContext();
                    }
                    if ((EditorApplication.timeSinceStartup - this.clickTime) < 0.3)
                    {
                        this.AddSelectedEventToState();
                    }
                    this.clickTime = EditorApplication.timeSinceStartup;
                }
                GUILayout.FlexibleSpace();
                GUILayout.Label(num.ToString(CultureInfo.CurrentCulture), style, new GUILayoutOption[0]);
                GUILayout.Space(10f);
                enabled = GUI.enabled;
                if (fsmEvent.IsSystemEvent)
                {
                    GUI.enabled = false;
                }
                if (FsmEditorGUILayout.DeleteButton() && EditorUtility.DisplayDialog("Delete Event", "Are you sure?" + ((num > 0) ? ("\n\nThe event is used by " + num + ((num > 1) ? " FSMs!" : " FSM")) : ""), "Yes", "No"))
                {
                    FsmEditor.Builder.DeleteEventFromAll(fsmEvent);
                    FsmEditor.EventManager.Reset();
                    FsmEvent.RemoveEventFromEventList(fsmEvent);
                    this.BuildFilteredList();
                    base.Repaint();
                }
                GUI.enabled = enabled;
                GUILayout.EndHorizontal();
            }
        }

        private void DoEventTable()
        {
            this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, new GUILayoutOption[0]);
            foreach (FsmEvent event2 in this.filteredEvents)
            {
                this.DoEventLine(event2);
            }
            GUILayout.Space(20f);
            GUILayout.EndScrollView();
            GUILayout.FlexibleSpace();
        }

        private void DoSearchField()
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, new GUILayoutOption[0]);
            string str = GUILayout.TextField(this.searchString, EditorStyles.toolbarTextField, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
            if (str != this.searchString)
            {
                this.searchString = str;
                this.BuildFilteredList();
            }
            if (FsmEditorGUILayout.ToolbarDeleteButton())
            {
                this.searchString = "";
                this.BuildFilteredList();
                base.Repaint();
            }
            if (FsmEditorGUILayout.ToolbarSettingsButton())
            {
                GenerateEventManagerMenu().ShowAsContext();
            }
            GUILayout.Space(-5f);
            EditorGUILayout.EndHorizontal();
        }

        private void DoTableHeaders()
        {
            EditorGUILayout.BeginHorizontal(new GUILayoutOption[0]);
            bool changed = GUI.changed;
            GUI.changed = false;
            GUILayout.BeginHorizontal(FsmEditorStyles.TableRowBox, new GUILayoutOption[0]);
            GUILayout.Label(new GUIContent(FsmEditorStyles.BroadcastIcon, "Global flag. Global events can be sent between FSMs."), new GUILayoutOption[] { GUILayout.MinWidth(20f) });
            this.sortByUsageCount = !GUILayout.Toggle(!this.sortByUsageCount, new GUIContent("Event", "Select or double-click event to add to the selected FSM. Right-click event to navigate to FSMs that use the event."), FsmEditorStyles.TableRowHeader, new GUILayoutOption[0]);
            GUILayout.FlexibleSpace();
            this.sortByUsageCount = GUILayout.Toggle(this.sortByUsageCount, new GUIContent("Used", "Number of FSMs that respond to the Event."), FsmEditorStyles.TableRowHeader, new GUILayoutOption[] { GUILayout.MaxWidth(40f) });
            GUILayout.Space(20f);
            GUILayout.EndHorizontal();
            if (!GUI.changed)
            {
                GUI.changed = changed;
            }
            EditorGUILayout.EndHorizontal();
            if (FsmEditorSettings.ShowHints)
            {
                GUILayout.Box("Right-click an Event to select FSMs that use the Event.\nUse the Global checkbox to send events between FSMs.", FsmEditorStyles.HintBox, new GUILayoutOption[0]);
            }
        }

        private static GenericMenu GenerateEventManagerMenu()
        {
            GenericMenu menu = new GenericMenu();
            menu.AddItem(new GUIContent("Hide Unused Events"), FsmEditorSettings.HideUnusedEvents, new GenericMenu.MenuFunction(GlobalEventsWindow.ToggleHideUnusedEvents));
            menu.AddItem(new GUIContent("Disable Window When Playing"), FsmEditorSettings.DisableEventBrowserWhenPlaying, new GenericMenu.MenuFunction(GlobalEventsWindow.ToggleDisableWindow));
            return menu;
        }

        private GenericMenu GenerateUsageContextMenu(FsmEvent fsmEvent)
        {
            int num;
            this.UpdateUseCount();
            GenericMenu menu = new GenericMenu();
            this.usageCount.TryGetValue(fsmEvent, out num);
            if (num == 0)
            {
                menu.AddDisabledItem(new GUIContent("No FSMs use this event..."));
                menu.AddSeparator("");
                if ((FsmEditor.SelectedFsm == null) || FsmEditor.SelectedFsm.HasEvent(this.selectedEvent.Name))
                {
                    menu.AddDisabledItem(new GUIContent("Add Event to FSM"));
                    return menu;
                }
                menu.AddItem(new GUIContent("Add Event to FSM"), false, new GenericMenu.MenuFunction(this.AddSelectedEventToState));
                return menu;
            }
            List<string> labels = new List<string>();
            foreach (Fsm fsm in FsmEditor.FsmList)
            {
                if ((fsm != null) && (fsm.Owner != null))
                {
                    foreach (FsmEvent event2 in fsm.Events)
                    {
                        if (event2.Name == fsmEvent.Name)
                        {
                            string text = FsmEditorUtility.GenerateUniqueLabel(labels, FsmEditorUtility.GetFullFsmLabel(fsm));
                            menu.AddItem(new GUIContent(text), FsmEditor.SelectedFsm == fsm, new GenericMenu.MenuFunction2(EditorCommands.SelectFsm), fsm);
                            labels.Add(text);
                        }
                    }
                }
            }
            menu.AddSeparator("");
            if ((FsmEditor.SelectedFsm == null) || FsmEditor.SelectedFsm.HasEvent(this.selectedEvent.Name))
            {
                menu.AddDisabledItem(new GUIContent("Add Event to FSM"));
                return menu;
            }
            menu.AddItem(new GUIContent("Add Event to FSM"), false, new GenericMenu.MenuFunction(this.AddSelectedEventToState));
            return menu;
        }

        public void OnDisable()
        {
            if (instance == this)
            {
                instance = null;
            }
        }

        public void OnEnable()
        {
            instance = this;
            base.title = "Events";
            base.minSize = new Vector2(200f, 200f);
            base.autoRepaintOnSceneChange = true;
            this.searchString = "";
            this.selectedEvent = null;
            this.BuildFilteredList();
        }

        public void OnFocus()
        {
            this.BuildFilteredList();
        }

        public void OnGUI()
        {
            if (FsmEditor.Instance == null)
            {
                base.Close();
            }
            else if (FsmEditorGUILayout.ToolWindowsCommonGUI(this))
            {
                if (EditorApplication.isPlaying && FsmEditorSettings.DisableEventBrowserWhenPlaying)
                {
                    GUILayout.Label("Disabled when playing. See Event Browser Settings Menu.", new GUILayoutOption[0]);
                    FsmEditorSettings.DisableEventBrowserWhenPlaying = !GUILayout.Toggle(!FsmEditorSettings.DisableEventBrowserWhenPlaying, "Enable Event Browser When Playing.", new GUILayoutOption[0]);
                    if (GUI.changed)
                    {
                        FsmEditorSettings.SaveSettings();
                    }
                }
                else
                {
                    this.DoSearchField();
                    this.DoTableHeaders();
                    this.DoEventTable();
                    if (Event.current.type == EventType.ContextClick)
                    {
                        GenerateEventManagerMenu().ShowAsContext();
                    }
                    this.DoEventEditor();
                    this.DoBottomPanel();
                    if (((Event.current.type == EventType.MouseUp) && (Event.current.button == 0)) && (GUIUtility.hotControl == 0))
                    {
                        GUIUtility.keyboardControl = 0;
                    }
                    if ((Event.current.type == EventType.MouseDown) && (GUIUtility.keyboardControl == 0))
                    {
                        this.selectedEvent = null;
                        base.Repaint();
                    }
                }
            }
        }

        private void RenameEvent()
        {
            FsmEditor.Builder.RenameEvent(this.selectedEvent.Name, this.newEventName);
            DeselectAll();
            FsmEditor.EventManager.DeselectAll();
            FsmEditor.RepaintAll();
        }

        public static void ResetView()
        {
            if (instance != null)
            {
                instance.selectedEvent = null;
                instance.BuildFilteredList();
                instance.Repaint();
            }
        }

        private void SelectEvent(FsmEvent fsmEvent)
        {
            if (Event.current != null)
            {
                GUIUtility.keyboardControl = 0;
            }
            if (fsmEvent != null)
            {
                this.newEventName = !fsmEvent.IsSystemEvent ? fsmEvent.Name : "";
                this.selectedEvent = fsmEvent;
                FsmEditor.EventManager.SelectEvent(fsmEvent, false);
            }
        }

        public static void SyncSelection(FsmEvent fsmEvent)
        {
            if (instance != null)
            {
                instance.SelectEvent(fsmEvent);
                instance.Repaint();
            }
        }

        private static void ToggleDisableWindow()
        {
            FsmEditorSettings.DisableEventBrowserWhenPlaying = !FsmEditorSettings.DisableEventBrowserWhenPlaying;
            FsmEditorSettings.SaveSettings();
        }

        private static void ToggleHideUnusedEvents()
        {
            FsmEditorSettings.HideUnusedEvents = !FsmEditorSettings.HideUnusedEvents;
            FsmEditorSettings.SaveSettings();
        }

        public void UpdateUseCount()
        {
            this.usageCount.Clear();
            this.unusedEvents.Clear();
            foreach (FsmEvent event2 in FsmEvent.EventList)
            {
                int num = CountEventUsage(event2);
                this.usageCount.Add(event2, num);
                if ((num == 0) && !event2.IsSystemEvent)
                {
                    this.unusedEvents.Add(event2);
                }
            }
            foreach (FsmEvent event3 in this.unusedEvents)
            {
                FsmEvent.EventList.Remove(event3);
            }
        }
    }
}

